#ifndef _OMDCL_PROGRAM_HPP_
#define _OMDCL_PROGRAM_HPP_

#include <iostream>
#include <string>
#include <omd/paramhandler.hpp>
#include <omd/toolkit.hpp>
#include <CL/cl.h>

#define OMDCL_MAX_KERNEL 8

/*
struct KernelArgStruct {
	size_t size;
	union {
		cl_char str[64];
		cl_int*  i;
		cl_uint* u;
		cl_float* f;
		cl_double* d;
		cl_mem*  m;
	} arg;
	KernelArgStruct(size_t sz, const void& val);
};
*/

struct KernelPack {
	string name;
	cl_kernel kernel;
	int argcount;
	KernelPack(string kn,cl_kernel kr) {
		name=kn;
		kernel=kr;
		argcount=0;
	}
};


class MDComputeProgram: public MDToolkit {
	friend class MDComputeMachine;
		
	class MDComputeMachine* machine;
	cl_program program;
	
	vector<KernelPack*> kernels;
	char* source_code;
	char compile_options[1024];

	size_t nd_global[3],nd_local[3],nd_offset[3];
	int nd_dimension;

private:	
	void ReadProgramFile(string source);
	void Create();
	
public:
	KernelPack* active_kernel;	
	KernelPack* SelectKernel(string kernel_name);
	KernelPack* GetActiveKernel(){return active_kernel;}
	
	void SetDimension(size_t cx);
	void SetDimension(size_t cx, size_t cy){die("not implemented");};
	void SetDimension(size_t cx, size_t cy, size_t, size_t cz){die("not implemented");}

	void ClearArgument();
	void PushArgument(size_t size, const void* arg);

	void Execute();
	void Execute(cl_event& evt);

	MDComputeProgram(class MDComputeMachine* mac,
					std::string programpath, 
					std::string cplopt="");
	virtual ~MDComputeProgram();	
};

#endif
